package com.rainbow.bam.base;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.JpaEntityInformationSupport;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.transaction.annotation.Transactional;

import com.rainbow.bam.core.DynamicSpecifications;
import com.rainbow.bam.core.SearchFilter;
import com.rainbow.bam.entity.PaginationRequest;
import com.rainbow.bam.entity.PaginationResponse;
import com.rainbow.bam.util.StringUtil;

@NoRepositoryBean
public class BaseCustomRepository<T, ID extends Serializable> extends SimpleJpaRepository<T, ID>
                                                                                                implements
                                                                                                BaseRepository<T, ID> {

    private static final String DEFAULT_SORT_COLUMN = "id"; //默认排序
    private static final int    DEFAULT_PAGE_SIZE   = 10;  //默认每页大小

    private final EntityManager entityManager;
    private final Class<T>      entityClass;
    @SuppressWarnings("unused")
    private final String        entityName;

    /**
     * 构造方法
     * 
     * @param domainClass
     * @param em
     */
    public BaseCustomRepository(Class<T> domainClass, EntityManager em) {
        this(JpaEntityInformationSupport.getMetadata(domainClass, em), em);
    }

    /**
     * 构造方法
     * 
     * @param entityInformation
     * @param entityManager
     */
    public BaseCustomRepository(final JpaEntityInformation<T, ?> entityInformation,
                                final EntityManager entityManager) {
        super(entityInformation, entityManager);
        this.entityManager = entityManager;
        this.entityClass = entityInformation.getJavaType();
        this.entityName = entityInformation.getEntityName();
    }

    /** 
     * @see com.rainbow.bam.base.BaseRepository#merge(java.lang.Object)
     */
    @Override
    public T merge(T obj) {
        obj = this.entityManager.merge(obj);
        return obj;
    }

    /** 
     * @see com.rainbow.bam.base.BaseRepository#findResultsByPagination(com.huatek.shop.entity.Pagination)
     */
    @Transactional(readOnly = true)
    @Override
    public PaginationResponse<T> findResultsByPagination(PaginationRequest paginationRequest) {
        PageRequest pageRequest = buildPageRequest(paginationRequest);
        Specification<T> spec = buildSpecification(paginationRequest.getSearchParams());
        Page<T> page = findAll(spec, pageRequest);
        PaginationResponse<T> pageResponse = new PaginationResponse<T>(page, entityClass);
        pageResponse.setContent(page.getContent());
        pageResponse.setCurrentPage(pageResponse.getCurrentPage()+1);//SPRING DATA JPA 分页页码从0开始，因此需要对返回的当前页码进行+1操作
        return pageResponse;
    }

    /**
     * 构建分页请求对象
     * 
     * @param pagination 分页信息实体对象
     * @return 分页请求对象
     */
    private PageRequest buildPageRequest(PaginationRequest pagination) {
        Sort sort = null;
        //如果排序字段为null 或者 排序字段为 ‘auto’ 时，默认按照主键进行降序排序
        if ("auto".equals(pagination.getSortColumn())
            || StringUtil.isBlank(pagination.getSortColumn())) {
            sort = new Sort(Direction.DESC, DEFAULT_SORT_COLUMN);
        } else {
            if (StringUtil.isBlank(pagination.getSortType())) {//如果排序字段不为空，但排序类型为空是默认为降序
                sort = new Sort(Direction.DESC, pagination.getSortColumn());
            } else {
                sort = new Sort(pagination.getSortType(), pagination.getSortColumn());//如果排序字段和排序类型均不为空，则设置排序属性
            }
        }
        pagination.setCurrentPage(pagination.getCurrentPage()-1);//SPRING DATA JPA 分页页码从0开始，因此需要对传递的当前页码进行-1操作
        int pageSize = 0;
        if (pagination.getPageSize() == 0) {
            pageSize = DEFAULT_PAGE_SIZE;
        } else {
            pageSize = pagination.getPageSize();
        }
        return new PageRequest(pagination.getCurrentPage(), pageSize, sort);
    }

    /**
     * 创建动态查询条件组合.
     */
    private Specification<T> buildSpecification(Map<String, Object> searchParams) {
        if (searchParams == null) {
            searchParams = new HashMap<String, Object>();
        }
        Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
        //DEMO 设置查询条件
        //filters.put("accountName", new SearchFilter("accountName", Operator.EQ, "harrison_han"));
        //filters.put("password", new SearchFilter("password", Operator.EQ, "111111"));
        Specification<T> spec = DynamicSpecifications.bySearchFilter(filters.values(), entityClass);
        return spec;
    }
    /**
     * HQL执行语句返回HQL语句对象集合
     * @param hql
     * @return
     */
    public List<T> findListByHql(String hql){
        Query query =  this.entityManager.createQuery(hql);
           List<T> result = query.getResultList();
           return result;
    }
    /**
     * 执行SQL语句返回指定对象集合
     * @param entityClass
     * @param sql
     * @return
     */
    public List<T> findAllBySql(Class<T> entityClass, String sql) {  
          //创建原生SQL查询QUERY实例,指定了返回的实体类型  
          Query query =  entityManager.createNativeQuery(sql,entityClass);  
          //执行查询，返回的是实体列表,  
          List<T> EntityList = query.getResultList();  
        return EntityList;  
    }  
}